//! Literal expression parsing (arrays, maps, structs, lambdas)

use super::Parser;
use crate::ast::expr::*;
use crate::ast::stmt::Statement;
use crate::ast::types::*;
use crate::error::{CompilerError, Result};
use crate::lexer::token::Token;

/// Parse array literal
pub fn parse_array_literal(parser: &mut Parser) -> Result<Option<Expression>> {
    parser.expect(&Token::LeftBracket)?;
    let mut elements = Vec::new();

    if !parser.check(&Token::RightBracket) {
        loop {
            if let Some(element) = super::parse_expression(parser)? {
                elements.push(element);
            }

            if !parser.consume(&Token::Comma)? {
                break;
            }
        }
    }

    parser.expect(&Token::RightBracket)?;

    Ok(Some(Expression::Array(ArrayExpr {
        elements,
        location: parser.current_location(),
    })))
}

/// Parse slice literal (Go-style: []T{...})
/// Example: Vector<int>{1, 2, 3}
/// Extended syntax: Vector<int>{1, 2, 3; cap: 10} or Vector<int>{cap: 100} or Vector<int>{42; count: 5}
pub fn parse_slice_literal(parser: &mut Parser) -> Result<Option<Expression>> {
    // Parse vector type Vector<T>
    let vector_type = super::super::type_parser::parse_type(parser)?;
    if vector_type.is_none() {
        return Err(CompilerError::syntax(
            parser.current_location().line,
            parser.current_location().column,
            "Expected vector type",
        ));
    }

    // Verify it's a vector type
    let element_type = match vector_type.unwrap() {
        Type::Vec(vector_type) => *vector_type.element_type,
        _ => {
            return Err(CompilerError::syntax(
                parser.current_location().line,
                parser.current_location().column,
                "Expected vector type (Vector<T>) for vector literal",
            ));
        }
    };

    // Parse {...} literal
    parser.expect(&Token::LeftBrace)?;

    let mut elements = Vec::new();
    let mut capacity = None;
    let mut count = None;

    if !parser.check(&Token::RightBrace) {
        // Check if this is a parameter-only syntax (identifier followed by colon)
        let is_param_syntax = matches!(
            parser.current.as_ref().map(|t| &t.token),
            Some(Token::Identifier(_))
        ) && parser
            .peek_ahead(1)
            .map_or(false, |t| matches!(t.token, Token::Colon));

        if !is_param_syntax {
            // Parse elements until semicolon or right brace
            loop {
                if parser.check(&Token::Semicolon) || parser.check(&Token::RightBrace) {
                    break;
                }

                if let Some(element) = super::parse_expression(parser)? {
                    elements.push(element);
                }

                if !parser.consume(&Token::Comma)? {
                    break;
                }
            }
        }

        // Check for semicolon-separated parameters
        let has_semicolon = parser.consume(&Token::Semicolon)?;

        if has_semicolon || is_param_syntax {
            // Parse parameters: cap: value, count: value
            loop {
                if parser.check(&Token::RightBrace) {
                    break;
                }

                // Parse parameter name (cap or count)
                if let Some(Token::Identifier(name)) = parser.current.as_ref().map(|t| &t.token) {
                    if name == "cap" {
                        parser.advance()?;
                        parser.expect(&Token::Colon)?;
                        capacity = super::parse_expression(parser)?.map(Box::new);
                    } else if name == "count" {
                        parser.advance()?;
                        parser.expect(&Token::Colon)?;
                        count = super::parse_expression(parser)?.map(Box::new);
                    } else {
                        return Err(CompilerError::syntax(
                            parser.current_location().line,
                            parser.current_location().column,
                            "Expected 'cap' or 'count' parameter",
                        ));
                    }
                } else {
                    return Err(CompilerError::syntax(
                        parser.current_location().line,
                        parser.current_location().column,
                        "Expected 'cap' or 'count' parameter",
                    ));
                }

                if !parser.consume(&Token::Comma)? {
                    break;
                }
            }
        }
    }

    parser.expect(&Token::RightBrace)?;

    // Validation: count requires exactly one element
    if count.is_some() && elements.len() != 1 {
        return Err(CompilerError::syntax(
            parser.current_location().line,
            parser.current_location().column,
            "count parameter requires exactly one element",
        ));
    }

    Ok(Some(Expression::Slice(SliceExpr {
        element_type,
        elements,
        capacity,
        count,
        location: parser.current_location(),
    })))
}

/// Parse map literal (Map<K, V>{k1: v1, k2: v2, ...})
/// Example: Map<String, int32>{"name": 100, "age": 30}
/// Empty map: Map<String, int32>{}
pub fn parse_map_literal(parser: &mut Parser) -> Result<Option<Expression>> {
    // Parse map type Map<K, V>
    let map_type = super::super::type_parser::parse_type(parser)?;
    if map_type.is_none() {
        return Err(CompilerError::syntax(
            parser.current_location().line,
            parser.current_location().column,
            "Expected map type",
        ));
    }

    // Verify it's a map type
    if !matches!(map_type, Some(Type::Map(_))) {
        return Err(CompilerError::syntax(
            parser.current_location().line,
            parser.current_location().column,
            "Expected map type (Map<K, V>) for map literal",
        ));
    }

    // Parse {...} literal
    parser.expect(&Token::LeftBrace)?;

    let mut entries = Vec::new();

    if !parser.check(&Token::RightBrace) {
        loop {
            let key = super::parse_expression(parser)?;
            parser.expect(&Token::Colon)?;
            let value = super::parse_expression(parser)?;

            if let (Some(key), Some(value)) = (key, value) {
                entries.push(MapEntry {
                    key,
                    value,
                    location: parser.current_location(),
                });
            }

            if !parser.consume(&Token::Comma)? {
                break;
            }
        }
    }

    parser.expect(&Token::RightBrace)?;

    Ok(Some(Expression::Map(MapExpr {
        entries,
        location: parser.current_location(),
    })))
}

/// Parse struct literal
pub fn parse_struct_literal(parser: &mut Parser) -> Result<Option<Expression>> {
    parser.expect(&Token::Struct)?;

    // Parse struct type
    let struct_type = super::super::type_parser::parse_type(parser)?;
    if struct_type.is_none() {
        return Err(CompilerError::syntax(
            parser.current_location().line,
            parser.current_location().column,
            "Expected struct type",
        ));
    }

    parser.expect(&Token::LeftBrace)?;

    let mut fields = Vec::new();

    if !parser.check(&Token::RightBrace) {
        loop {
            if let Some(Token::Identifier(field_name)) = parser.peek().map(|t| &t.token) {
                let name = field_name.clone();
                parser.advance()?;
                parser.expect(&Token::Colon)?;

                let value = super::parse_expression(parser)?;
                if let Some(value) = value {
                    fields.push(FieldInit {
                        name,
                        value,
                        location: parser.current_location(),
                    });
                }
            }

            if !parser.consume(&Token::Comma)? {
                break;
            }
        }
    }

    parser.expect(&Token::RightBrace)?;

    Ok(Some(Expression::Struct(StructExpr {
        struct_type: struct_type.unwrap(),
        fields,
        location: parser.current_location(),
    })))
}

/// Parse lambda expression or function literal
/// NRC syntax: func(name type, name type) return_type { body }
pub fn parse_lambda(parser: &mut Parser) -> Result<Option<Expression>> {
    let loc = parser.current_location();
    parser.expect(&Token::Fn)?; // Token::Fn corresponds to "func" keyword
    parser.expect(&Token::LeftParen)?;

    let mut parameters = Vec::new();

    if !parser.check(&Token::RightParen) {
        loop {
            // NRC syntax: name type (no colon)
            if let Some(Token::Identifier(param_name)) = parser.peek().map(|t| &t.token) {
                let name = param_name.clone();
                parser.advance()?;

                // Parse parameter type (no colon before type)
                let param_type = super::super::type_parser::parse_type(parser)?;
                if let Some(param_type) = param_type {
                    parameters.push(crate::ast::types::Parameter {
                        name,
                        param_type,
                        default_value: None,
                        location: parser.current_location(),
                    });
                }
            }

            if !parser.consume(&Token::Comma)? {
                break;
            }
        }
    }

    parser.expect(&Token::RightParen)?;

    // Parse return type (Go-style: directly after params, no arrow)
    let return_type = if !parser.check(&Token::LeftBrace) {
        super::super::type_parser::parse_type(parser)?
    } else {
        None
    };

    // Parse body (must be a block expression)
    parser.expect(&Token::LeftBrace)?;
    let body_block = crate::parser::parse_block(parser)?;

    // Convert block to block expression
    // Extract the last statement as final_expr if it's an expression statement
    let mut statements = body_block.statements;
    let final_expr = if let Some(last_stmt) = statements.last() {
        if let Statement::Expression(expr) = last_stmt {
            // Remove the last statement and use it as final expression
            let expr_clone = expr.clone();
            statements.pop();
            Some(Box::new(expr_clone))
        } else {
            None
        }
    } else {
        None
    };

    let body = Expression::Block(BlockExpr {
        statements,
        final_expr,
        location: loc,
    });

    let lambda = LambdaExpr {
        parameters: parameters.clone(),
        return_type: return_type.clone(),
        captures: Vec::new(),
        body: Box::new(body),
        location: loc,
    };

    // Create function type from lambda signature
    let param_types: Vec<Type> = parameters.iter().map(|p| p.param_type.clone()).collect();
    let function_type = Type::Function(FunctionType {
        parameter_types: param_types,
        return_type: return_type.map(Box::new),
        variadic: false,
        location: loc,
    });

    // Return as FunctionLiteral wrapping the lambda
    Ok(Some(Expression::FunctionLiteral(FunctionLiteralExpr {
        function_name: None,
        lambda: Some(Box::new(lambda)),
        function_type: Some(function_type),
        location: loc,
    })))
}

/// Parse new expression for creating reference-counted objects
pub fn parse_new_expression(parser: &mut Parser) -> Result<Option<Expression>> {
    parser.expect(&Token::New)?;

    // Parse type name
    if let Some(Token::Identifier(type_name)) = parser.peek().map(|t| &t.token) {
        let name = type_name.clone();
        parser.advance()?;

        // Parse initializer if present
        let initializer = if parser.consume(&Token::LeftBrace)? {
            let mut fields = Vec::new();

            if !parser.check(&Token::RightBrace) {
                loop {
                    if let Some(Token::Identifier(field_name)) = parser.peek().map(|t| &t.token) {
                        let field_name = field_name.clone();
                        parser.advance()?;
                        parser.expect(&Token::Colon)?;

                        let value = super::parse_expression(parser)?;
                        if let Some(value) = value {
                            fields.push(FieldInit {
                                name: field_name,
                                value,
                                location: parser.current_location(),
                            });
                        }
                    }

                    if !parser.consume(&Token::Comma)? {
                        break;
                    }
                }
            }

            parser.expect(&Token::RightBrace)?;

            Some(Expression::Struct(StructExpr {
                struct_type: Type::Struct(StructType {
                    name: name.clone(),
                    type_args: vec![],
                    location: parser.current_location(),
                }),
                fields,
                location: parser.current_location(),
            }))
        } else {
            None
        };

        Ok(Some(Expression::New(NewExpr {
            type_name: name,
            initializer: initializer.map(Box::new),
            location: parser.current_location(),
        })))
    } else {
        Err(CompilerError::syntax(
            parser.current_location().line,
            parser.current_location().column,
            "Expected type name after 'new'",
        ))
    }
}
